package bj.actor

import scala.swing.event.Event
import scala.actors.Actor
import scala.swing.Publisher
import scala.swing.event.Event
import scala.swing.Swing.onEDT
import scala.actors.remote.RemoteActor
import Actor._
import scala.actors.remote.RemoteActor.{ alive, register }
import scala.actors.remote.RemoteActor
import scala.actors.remote.Node
import scala.actors.AbstractActor

/** 
 * Case class Send is used to send a message from a GUI to an Actor.  The GUI declares an Intermediator,
 * which extends Actor, and sends messages using the Send case class to the Actor indicated in the
 * declare for Intermediator.  The Actor responds by sending messages back to the Intermediator (as sender).
 * Since the GUI is listening to the Intermediator, the GUI can respond to messages from an Actor the same
 * way it responds to events like button clicks.  
 */
case class Send(event: Any)(implicit intermediator: Intermediator) {
  intermediator ! this
}

/**
 * Receive is used in the reactions block of the GUI to react to messages received from the remote actor
 */
case class Receive(event: Any) extends Event

/**
 * Intermediator sets up this whole shebang.  It acts as an actor from within the GUI and relays any
 * messages by use of the Receive case class to the reactions block in the GUI.  Intermediator also
 * uses the Send case class to send messages to the "application" Actor
 */
case class Intermediator(application: AbstractActor) extends Actor with Publisher {
  start()

  def act() {
    loop {
      react {
        case Send(evt) => application ! evt
        case evt => onEDT(publish(Receive(evt)))
      }
    }
  }
}

/** TimeMe causes the timer to wait the specified amount of time then send the specified case class back to the sender */
case class TimeMe(timeInMicroseconds : Int, timerId : Any)

/** the Timer object is used by the Dealer to offer insurance for approximately 3 seconds.  Having the Timer block instead of having
 * the Dealer block allows the Dealer to process incoming messages (for instance, if a player does actually purchase insurance).
 * Timer reacts to one case class, TimeMe.  When it is received, the Timer sleeps for the specified time, then sends the
 * specified case class back to the sender.  The sender processes his "resume" case class the same as any other case class
 */
case object Timer extends Actor {
  start()
  def act() {
    loop {
      react {
      case TimeMe(timelimit,timerId) => 
        Thread.sleep(timelimit)
        sender ! timerId
    }
  }
}
}
